# uncompyle6 version 3.2.3
# Python bytecode 3.6 (3379)
# Decompiled from: Python 3.6.8 |Anaconda custom (64-bit)| (default, Feb 21 2019, 18:30:04) [MSC v.1916 64 bit (AMD64)]
# Embedded file name: api\handlers\frontend\notifications.py
import logging
from sqlalchemy import desc as sql_desc
from sqlalchemy import select as sql_select
from sqlalchemy.sql.functions import count as sql_count
from api.classes.frontend.auto import (
    ClsNotificationsResponse,
    ClsNotification,
    ClsPagination,
    ClsNotificationCountResponse,
)
from api.filters import Filters
from api.filters.sqlalchemy_adapter import get_sqlachemy_filter
from api.handlers.frontend import FrontendResourceHandler
from db import Connection
from db.data.users import is_master_user
from db.tables.events import EventRow, EventsTable
from db.tables.users import UserRow, UsersTable
from server.http_responses.http_status_codes import *
from server.http_responses.http_errors import Http404

logger = logging.getLogger("api.Intents")
event_filters = {
    "keys": {
        "consumed": {"value_type": "boolean", "operators": ("eq", "ne")},
        "severity": {
            "value_type": "int",
            "multiple_values": True,
            "operators": ("eq", "ne", "le", "ge", "lt", "gt"),
        },
        "resource_type": {"value_type": "int", "operators": ("eq", "ne")},
        "resource_id": {"value_type": "uuid4", "operators": ("eq", "ne")},
        "type_id": {
            "value_type": "int",
            "multiple_values": True,
            "operators": ("eq", "ne", "le", "ge", "lt", "gt"),
        },
    }
}


class Notifications(FrontendResourceHandler):
    @staticmethod
    def __process_notification(notification):
        name = (" ").join(
            (
                notification.first_name if notification.first_name else "",
                notification.last_name if notification.last_name else "",
            )
        )
        notification_ext = dict(
            consumed=notification.consumed,
            notification_id=str(notification.event_id),
            type_id=notification.type_id,
            resource_type=notification.resource_type,
            resource_id=notification.resource_id,
            data=notification.data,
            email=notification.email,
            user_id=notification.user_id,
            name=name,
            created=notification.created,
            severity=notification.severity,
        )
        return notification_ext

    def get_events(self, l, q=None, c=None, unconsumed_notifications_only=False, **_):
        limit = min(l, 100) if l is not None else 100
        c = int(c) if c is not None else None
        filters = Filters(event_filters, q)
        select_from = EventsTable.outerjoin(
            UsersTable, UserRow.user_id == EventRow.user_id
        )
        query = sql_select(
            (EventRow, UserRow.email, UserRow.first_name, UserRow.last_name)
        ).select_from(select_from)
        if is_master_user(self.request_user):
            query = query.where(EventRow.owner_id == self.request_user["user_id"])
        else:
            query = query.where(EventRow.user_id == self.request_user["user_id"])
        for filter_key, filter_expression in filters.data.items():
            if filter_key == "consumed":
                query = query.where(
                    get_sqlachemy_filter(
                        filter_expression,
                        EventRow.consumed,
                        filters.descriptor["keys"][filter_key],
                    )
                )
            elif filter_key == "severity":
                query = query.where(
                    get_sqlachemy_filter(
                        filter_expression,
                        EventRow.severity,
                        filters.descriptor["keys"][filter_key],
                    )
                )
            elif filter_key == "resource_type":
                query = query.where(
                    get_sqlachemy_filter(
                        filter_expression,
                        EventRow.resource_type,
                        filters.descriptor["keys"][filter_key],
                    )
                )
            elif filter_key == "resource_id":
                query = query.where(
                    get_sqlachemy_filter(
                        filter_expression,
                        EventRow.resource_id,
                        filters.descriptor["keys"][filter_key],
                    )
                )
            elif filter_key == "type_id":
                query = query.where(
                    get_sqlachemy_filter(
                        filter_expression,
                        EventRow.type_id,
                        filters.descriptor["keys"][filter_key],
                    )
                )

        if c:
            query = query.where(EventRow.event_id <= c)
        if unconsumed_notifications_only:
            query = query.where(EventRow.consumed.is_(False))
        query = query.limit(limit + 1).order_by(sql_desc(EventRow.event_id))
        notifications = []
        next_cursor = None
        with Connection(self.current_shard_name) as (db_connection):
            i = 0
            for notification in db_connection.execute(query).fetchall():
                if i < limit:
                    notifications.append(
                        self._Notifications__process_notification(notification)
                    )
                    i += 1
                else:
                    next_cursor = notification.event_id

        return ClsNotificationsResponse(
            notifications=notifications,
            pagination=ClsPagination(
                next_cursor=str(next_cursor) if next_cursor is not None else None,
                previous_cursor=str(c) if c is not None else None,
            ),
        )

    def get_event(self, notification_id, **_):
        notification_id = int(notification_id)
        select_from = EventsTable.outerjoin(
            UsersTable, UserRow.user_id == EventRow.user_id
        )
        query = sql_select(
            (EventRow, UserRow.email, UserRow.first_name, UserRow.last_name)
        ).select_from(select_from)
        query = query.where(EventRow.event_id == notification_id)
        if is_master_user(self.request_user):
            query = query.where(EventRow.owner_id == self.request_user["user_id"])
        else:
            query = query.where(EventRow.user_id == self.request_user["user_id"])
        with Connection(self.current_shard_name) as (db_connection):
            notification = db_connection.execute(query).fetchone()
            if notification is None:
                return Http404()
            return ClsNotification(
                **self._Notifications__process_notification(notification)
            )

    def get_unconsumed_notification_count(self, **_):
        query = sql_select((sql_count(EventRow.event_id),)).where(
            EventRow.consumed.is_(False)
        )
        if is_master_user(self.request_user):
            query = query.where(EventRow.owner_id == self.request_user["user_id"])
        else:
            query = query.where(EventRow.user_id == self.request_user["user_id"])
        with Connection(self.current_shard_name) as (db_connection):
            c = db_connection.execute(query).scalar()
            if c is None:
                c = 0
            return ClsNotificationCountResponse(count=c)

    def get_notifications(self, l, q=None, c=None, **_):
        return self.get_events(l, q, c, unconsumed_notifications_only=True)

    def consume_all(self, **_):
        query = (EventsTable.update(values=dict(consumed=True))).where(
            EventRow.consumed.is_(False)
        )
        if is_master_user(self.request_user):
            query = query.where(EventRow.owner_id == self.request_user["user_id"])
        else:
            query = query.where(EventRow.user_id == self.request_user["user_id"])
        with Connection(self.current_shard_name) as (db_connection):
            db_connection.execute(query)
        return Http204

    def consume_notification(self, notification_id, **_):
        notification_id = int(notification_id)
        query = (
            (EventsTable.update(values=dict(consumed=True)))
            .where(EventRow.event_id == notification_id)
            .where(EventRow.consumed.is_(False))
        )
        if is_master_user(self.request_user):
            query = query.where(EventRow.owner_id == self.request_user["user_id"])
        else:
            query = query.where(EventRow.user_id == self.request_user["user_id"])
        with Connection(self.current_shard_name) as (db_connection):
            db_connection.execute(query)
        return Http204()
